<?php

namespace app\zyhsapi\model\comment;

use app\common\cachemodel\ZlcrAstr;
use app\common\lib\Util;
use app\zyhsapi\model\BaseCacheZyhs;
use app\zyhsapi\model\ZyhsAstrBindUser;
use app\zyhsapi\model\ZyhsBlacklist;
use app\zyhsapi\model\ZyhsInteractiveMessage;
use app\zyhsapi\model\ZyhsPxyzUserQuestion;
use app\zyhsapi\model\ZyhsUser;
use XznsTools\cache\zyhs\CacheManageZyhs;

class ZyhsArticleComment extends BaseCacheZyhs
{
    protected $table = 'good_wechat.zyhs_article_comment';

    protected $cacheModel = 'zyhs.content_comment';

    protected static $userAvatarNicknameData = [];

    /**
     * 评论添加
     * @param array $userInfo 用户信息
     * @param array $data
     * @return array
     * @throws \Exception
     */
    public function commentAdd(array $userInfo, array $data = [])
    {
        try
        {   // 获取 用户绑定咨询师信息
            $userBindAstrInfo = (new ZyhsAstrBindUser())->getAstrBindUserData();
            if (isset($userBindAstrInfo[$userInfo['id']]))
            {   //  占星师 发生评论    判断是否已经发过评论了
                $commentNum = $this->where(['uid' => $data['uid'], 'type' => $data['type'], 'aid' => $data['aid'], 'status' => 1])->count();
                if ($commentNum)
                {
                    return [
                        'status' => false,
                        'msg' => '占星师身份只能发表一次看法',
                    ];
                }
            }
            $cacheKey = 'comment_num';
            $articleModel = new ZyhsPxyzUserQuestion();
            //获取对应的内容信息
            switch ($data['type'])
            {
                case 1:
                    $article = $articleModel->getInfoById($data['aid'], ['comment_num', 'uid', 'avatar_id', 'nickname', 'good_num', 'read_num', 'astr_reply_num']);
                    break;
                default:
                    $article = [];
            }
            if ($article)
            {   // 添加 评论
                $commentId = (int)$this->insertGetId($data);
                // 评论列表信息 当前评论ID
                //  添加 时间排序
                $this->listDataAdd($data['type'], [$commentId => $data['create_time']], $data['aid']);
                if (!isset($userBindAstrInfo[$userInfo['id']]))
                {   //  非占星师回复  推荐值 排序   缓存半小时  每半小时更新一次  列表需要显示回复+点赞最多的三条
                    CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('recommended_sort', $data['type'] . ':' . $data['aid'])->listAdd([$commentId => "0.{$data['create_time']}"], 0, 'recommended_sort');
                }
                //  如果是咨询师   缓存半小时  每半小时更新一次  所以不需要添加到缓存
                switch ($data['type'])
                {
                    case 1:
                        // 更新 内容 评论数 ---------------------------------------------------------------
                        $d = [
                            'good_num' => $article['good_num'],    // 点赞数
                            'comment_num' => $article['comment_num'], // 评论总数
                            'read_num' => $article['read_num'],    // 已读总数
                        ];
                        if (isset($userBindAstrInfo[$userInfo['id']]))
                        {   // 如果时 占星师 回复 直接更新入库
                            $d['astr_reply_num'] = $article['astr_reply_num'] + 1;
                        }
                        $articleModel->updateCommentNumData($data['aid'], $cacheKey, $d);
                        // 添加 用户互动消息 ---------------------------------------------------------------
                        if ($article['uid'] !== $userInfo['id'])
                        {   //    不是给自己 发布的内容  评论的情况  添加互动消息
                            $blacklistUids = (new ZyhsBlacklist())->getBlackUids(1, $article['uid']); // 获取 黑名单 uid
                            if (!$blacklistUids || !in_array($userInfo['id'], $blacklistUids))
                            {   // 黑名单为空 或 不是 黑名单用户
                                $d = [
                                    'atype' => 1,
                                    'aid' => $data['aid'],
                                    'type' => 2,
                                    'comment_id' => 0,
                                    'reply_id' => 0,
                                    'uid' => $article['uid'],
                                    'uid1' => $userInfo['id'],
                                    'res_id' => $commentId,
                                ];
                                (new ZyhsInteractiveMessage())->saveData($d);
                            }
                        }
                        //  添加我参与的 ---------------------------------------------------------------
                        (new ZyhsArticleMyInteracted())->setMyInteracted($userInfo['id'], 1, $data['aid'], $commentId, 0);
                        break;
                }
            } else
            {
                return [
                    'status' => false,
                    'msg' => '请求异常，请稍后再试～',
                ];
            }
        }
        catch (\Exception $e)
        {
            return [
                'status' => false,
                'msg' => '服务异常，请稍后再试',
            ];
        }

        // 组合 返回输出数据
        $resData = [];
        switch ($data['type'])
        {
            case 1:
                $astrId = $userBindAstrInfo[$userInfo['id']] ?? 0;
                if ($astrId)
                {   // 占星师 回复 消息  头像 和昵称 使用占星师 的头像和昵称
                    $astrInfo = (new ZlcrAstr())->getInfoById($astrId, ['avatar', 'nickname']);
                    $avatar = $astrInfo['avatar'];
                    $nickname = $astrInfo['nickname'];
                } else
                {
                    if ($userInfo['id'] === $article['uid'])
                    {
                        $avatarNicknameList = config('pxyz.avatar_list');
                        $avatar = $avatarNicknameList[$article['avatar_id']];
                        $nickname = $article['nickname'];
                        $ownerTag = '本体';
                    } else
                    {
                        $avatar = $userInfo['avatar'];
                        $nickname = $userInfo['nickname'];
                    }
                }
                $resData = [
                    'id' => $commentId,
                    'avatar' => $avatar,
                    'nickname' => $nickname,
                    'create_time' => '刚刚',
                    'content' => $data['content'],
                    'good_num' => 0,
                    'is_good' => 0,
                    'is_self' => 1,
                    'astr_id' => $astrId,
                    'owner_tag' => $ownerTag ?? '',
                    'reply_list' => [],
                    'reply_num' => 0,
                ];
                break;
        }

        return [
            'status' => true,
            'id' => $commentId,
            'data' => $resData,
        ];
    }

    /**
     * 评论 删除
     * @param int $aType
     * @param int $aid
     * @param int $id
     * @return bool
     */
    public function commentDel(int $aType, int $aid, int $id): bool
    {
        try
        {
            // 评论 删除
            $this->where(['id' => $id])->update(['status' => 0, 'del_type' => 1, 'delete_time' => time()]);

            CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $id)->rmCache();
            //  删除 评论 时间排序
            $this->listDataDel($aType, [$id], $aid);
            $key = "{$aType}:{$aid}";
            //  删除 评论 推荐排序
            CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('recommended_sort', $key)->delJudge($id, 'recommended_sort');
            //  删除 评论 占星师推荐排序
            CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('astr_comment_recommended_sort', $key)->delJudge($id, 'astr_comment_recommended_sort');

            return true;
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return false;
        }
    }

    /**
     * 获取 内容 评论 推荐值排序 排序IDS
     * @param int $type
     * @param int $aid
     * @param int $limit 小于等于0时 全部返回
     * @return array|mixed
     * @throws \Exception
     */
    public function getContentRecommendedSortIds(int $type, int $aid, int $limit)
    {
        // 获取 绑定咨询师的 用户uid
        $userBindAstrInfo = (new ZyhsAstrBindUser())->getAstrBindUserData();
        $astrUids = array_keys($userBindAstrInfo);

        $resData = CacheManageZyhs::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('recommended_sort', "{$type}:{$aid}")
            ->setPage(-1)
            ->setSort('desc')
            ->setListCacheTime(1800)    // 半小时 过期时间
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($type, $aid, $astrUids)
            {
                try
                {
                    $data = $this->where(['status' => 1, 'type' => $type, 'aid' => $aid])->whereNotIn('uid', $astrUids)->column('reply_num,good_num', 'id');
                    $rData = [];
                    foreach ($data as $id => $questionItem)
                    {
                        // $recommendedNum = $questionItem['comment_num'] * 5 + $questionItem['same_num'] * 3 + $questionItem['read_num'] * 2;
                        $recommendedNum = $questionItem['reply_num'] + $questionItem['good_num'];

                        $rData[$id] = $recommendedNum + ($id / 100000000);
                    }

                    if ($rData)
                    {
                        arsort($rData);
                    }
                    $resData = [];
                    foreach ($rData as $id => $resDatum)
                    {
                        $resData[$id] = ['recommended_num' => $resDatum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'recommended_num', 0, 'recommended_sort');

        $ids = array_keys($resData['data']);
        $num = count($ids);

        if ($limit <= 0 || $num <= $limit)
        {
            return $ids;
        } else
        {
            return array_slice($ids, 0, $limit);
        }
    }

    /**
     * 获取 内容 占星师回复评论 推荐值排序 排序IDS
     * @param int $aType 1=>平行宇宙
     * @param int $aid
     * @return array
     * @throws \Exception
     */
    public function getContentAstrReplyRecommendedSortIds(int $aType, int $aid)
    {
        // 获取 绑定咨询师的 用户uid
        $userBindAstrInfo = (new ZyhsAstrBindUser())->getAstrBindUserData();
        $astrUids = array_keys($userBindAstrInfo);
        if (empty($astrUids))
        {   // 还没有用户 绑定过咨询师
            return [];
        }
        $resData = CacheManageZyhs::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('astr_comment_recommended_sort', "{$aType}:{$aid}")
            ->setPage(-1)
            ->setListCacheTime(1800)    // 半小时 过期时间
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($aType, $aid, $astrUids)
            {
                try
                {
                    $data = $this->where(['status' => 1, 'type' => $aType, 'aid' => $aid])->whereIn('uid', $astrUids)->column('reply_num,good_num', 'id');
                    $rData = [];
                    foreach ($data as $id => $questionItem)
                    {   // $recommendedNum = $questionItem['comment_num'] * 5 + $questionItem['same_num'] * 3 + $questionItem['read_num'] * 2;
                        $recommendedNum = $questionItem['reply_num'] + $questionItem['good_num'];
                        $rData[$id] = $recommendedNum + ($id / 100000000);
                    }

                    if ($rData)
                    {
                        arsort($rData);
                    }
                    $resData = [];
                    foreach ($rData as $id => $resDatum)
                    {
                        $resData[$id] = ['recommended_num' => $resDatum];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'recommended_num', 0, 'astr_comment_recommended_sort');

        if ($resData['data'])
        {
            return array_keys($resData['data']);
        } else
        {
            return [];
        }
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array|false|string
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            $data = $this->where('id', 'in', $ids)
                ->column('id,uid,status,type,aid,good_num,content,reply_num,del_type,del_aid,create_time,delete_time', 'id');
        }
        catch (\Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);

        return $this->dataInit($resData);
    }

    public function dataInit(array $resData): array
    {
        foreach ($resData as $orderId => $questionItemData)
        {
            $resData[$orderId] = arrayKeyData2int($questionItemData, ['id', 'status', 'uid', 'type', 'aid', 'good_num', 'reply_num', 'del_type', 'del_aid', 'create_time', 'delete_time']);
        }
        return $resData;
    }

    /**
     * @param $commentId
     * @param string $cacheKey good_num | reply_num
     * @param array $data ['good_num' =>0,'reply_num' =>0]
     * @return void
     * @throws \Exception
     */
    public function updateReplyNumData($commentId, string $cacheKey, array $data, int $inc = 1): void
    {
        $cache = CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $commentId);
        $data[$cacheKey] = $data[$cacheKey] + $inc;
        if ($inc < 0 && $data[$cacheKey] < 0)
        {
            $data[$cacheKey] = 0;
            $cache->setCache([$cacheKey => 0]);
        } else
        {   // 更新 缓存
            $cache->setCacheInc($cacheKey, 'details', $inc);
        }
        // 基数记录增加   用于减少更新数据库频率
        $addNum = $cache->setCacheKeyDetail('inc_base_num', $commentId)->setCacheInc($cacheKey, 'inc_base_num', 1);
        if ($addNum >= ($cache->cacheKey['base_max'] ?? 5))    // 咨询师 回复时 必须更新
        {   // 删除记录
            $cache->rmCache('inc_base_num');
            // 更新 入库
            $this->where(['id' => $commentId])->update($data);
        }
    }

    public function getCommentTimeSortIdsCache(int $aType, int $aid)
    {
        $resData = CacheManageZyhs::getInstance()
            ->setCacheConfig($this->cacheModel, $aType)
            ->setPage(-1)
            ->setSort('desc')
            ->setListKeyType($aid)
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($aType, $aid)
            {
                try
                {
                    $data = $this->where(['status' => 1, 'type' => $aType, 'aid' => $aid])->order('create_time ' . $sortType)->column('create_time', 'id');
                    $resData = [];
                    foreach ($data as $id => $createTime)
                    {
                        $resData[$id] = ['create_time' => $createTime];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'create_time', 0);

        return $resData['data'] ? array_keys($resData['data']) : [];
    }

    /**
     * 获取 评论列表IDS 数据信息
     * @param int $aType
     * @param int $aid
     * @param int $minId
     * @param int $type 1 =>全部 2=>只看用户
     * @param array $blacklistUids
     * @param int $limit
     * @return array
     * @throws \Exception
     */
    public function getCommentIdsData(int $aType, int $aid, int $minId, int $type, array $blacklistUids, array $userBindAstrInfo, int $limit = 10)
    {
        // 获取 咨询师 回复评论 推荐值排序 排序IDS
        $astrCommentIds = $this->getContentAstrReplyRecommendedSortIds($aType, $aid);
        // 获取 回复评论 推荐值排序 排序IDS
        $recommendedSortIds = $this->getContentRecommendedSortIds($aType, $aid, 0);
        $recommendedSortIds = array_diff($recommendedSortIds, $astrCommentIds);
        // 获取时间排序 评论IDS
        $cidsAll = $this->getCommentTimeSortIdsCache($aType, $aid);
        $totalNum = count($cidsAll);
        // 第一页显示 咨询师评论IDS
        if ($type === 1)
        {   // 查看全部
            $astrCids = [];
            foreach ($astrCommentIds as $idItem)
            {
                $commentInfo = $this->getInfoById($idItem);
                if ($commentInfo && !in_array($commentInfo['uid'], $blacklistUids, true))
                {
                    $astrCids[] = $idItem;
                }
                if (count($astrCids) >= 2)
                {
                    break;
                }
            }
        } else
        {   // 只看用户
            $astrCids = [];
        }
        $rCids = [];
        foreach ($recommendedSortIds as $idItem)
        {
            $commentInfo = $this->getInfoById($idItem);
            if ($commentInfo && !in_array($commentInfo['uid'], $blacklistUids, true))
            {
                $rCids[] = $idItem;
            }
            if (count($rCids) >= 2)
            {
                break;
            }
        }

        $cidsAll = array_diff($cidsAll, $rCids, $astrCids);
        $cidsAll = array_merge($astrCids, $rCids, $cidsAll);
        $resDataList = [];
        $surplusNum = 0;
        $newMinId = 0;
        $isStart = false;
        foreach ($cidsAll as $idItem)
        {
            if ($minId > 0 && $isStart === false)
            {
                if ($minId === (int)$idItem)
                {
                    $isStart = true;
                }
                continue;
            }
            if (count($resDataList) >= $limit)
            {
                $surplusNum++;
            } else
            {
                $commentInfo = $this->getInfoById($idItem);
                if ($commentInfo && !in_array($commentInfo['uid'], $blacklistUids, true))
                {
                    if ($type === 2 && isset($userBindAstrInfo[$commentInfo['uid']]))
                    {   // 只看占星师的时候 占星师的回复 跳过
                        continue;
                    }
                    $resDataList[] = $commentInfo;
                    $newMinId = $idItem;
                }
            }
        }

        return [
            'total' => $totalNum,
            'surplus_num' => $surplusNum,
            'min_id' => $newMinId,
            'data' => $resDataList,
        ];
    }

    /**
     * 获取 评论列表
     * @param array $userInfo 用户信息
     * @param int $aType 内容类型 1=>平行宇宙
     * @param int $aid 内容ID
     * @param int $minId 剩余数据数量 为0时不能再向上翻页了
     * @param int $type 1=>全部 2=>只看用户
     * @return array
     * @throws \Exception
     */
    public function getCommentList(array $userInfo, int $aType, int $aid, int $minId, int $type)
    {
        $uid = $userInfo['id'] ?? 0;
        switch ($aType)
        {
            case 1:
                $articleInfo = (new ZyhsPxyzUserQuestion())->getInfoById($aid, ['uid', 'status', 'avatar_id', 'nickname']);
                break;
            default:
                $articleInfo = null;
        }
        if (!$articleInfo)
        {   // 内容不存在  返回数据为空
            return [
                'total' => 0,
                'ids' => [],
            ];
        }
        // 获取 黑名单用户 uid
        $blacklistUids = (new ZyhsBlacklist())->getBlackUids(1, $uid);
        //  获取绑定 占星师 的用户列表
        $userBindAstrInfo = (new ZyhsAstrBindUser())->getAstrBindUserData();
        $zyhsArticleCommentGoodModel = new ZyhsArticleCommentGood();
        $zyhsArticleCommentReplyModel = new ZyhsArticleCommentReply();
        //  获取用户点赞 评论ids列表
        $goodCommentIds = $uid ? $zyhsArticleCommentGoodModel->getUserCommentGoodCids($uid, 1) : [];
        //  用户点赞 评论回复ids列表
        $goodCommentReplyIds = $uid ? $zyhsArticleCommentGoodModel->getUserCommentGoodCids($uid, 2) : [];

        $idDatas = $this->getCommentIdsData($aType, $aid, $minId, $type, $blacklistUids, $userBindAstrInfo, 10);
        $resData = [];
        $avatarNicknameConfig = config('pxyz');
        foreach ($idDatas['data'] as $dataItem)
        {
            $ownerTag = '';
            if ($articleInfo['uid'] === $dataItem['uid'])
            {   // 发布内容 的 评论   【本人】
                $avatar = $avatarNicknameConfig['avatar_list'][$articleInfo['avatar_id']];
                $nickname = $articleInfo['nickname'];
                $ownerTag = '本体';
            } else
            {   // 非本人
                $userAvatarNicknameData = $this->getUserAvatarNickname($dataItem['uid'], $userBindAstrInfo);
                $avatar = $userAvatarNicknameData['avatar'];
                $nickname = $userAvatarNicknameData['nickname'];
            }
            $replyList = $zyhsArticleCommentReplyModel->getRecommendCommentReplyDataList($dataItem['id'], $type, 0, $blacklistUids, $userBindAstrInfo, ['uid', 'create_time', 'content', 'good_num', 'id', 'uid2'], 3);
            $resReplyData = [];
            $replyMinId = 0;
            foreach ($replyList['data'] as $replyItem)
            {
                if ($articleInfo['uid'] === $replyItem['uid'])
                {   // 发布内容 的 评论   【本人】
                    $replyAvatar = $avatarNicknameConfig['avatar_list'][$articleInfo['avatar_id']];
                    $replyNickname = $articleInfo['nickname'];
                } else
                {   // 非本人
                    $userAvatarNicknameData = $this->getUserAvatarNickname($replyItem['uid'], $userBindAstrInfo);
                    $replyAvatar = $userAvatarNicknameData['avatar'];
                    $replyNickname = $userAvatarNicknameData['nickname'];
                }

                if ($replyItem['uid2'])
                {   // 获取@用户uid
                    if ($articleInfo['uid'] === $replyItem['uid2'])
                    {   // 发布内容 的 评论   【本人】
                        $nickname2 = $articleInfo['nickname'];
                    } else
                    {
                        $userAvatarNicknameData = $this->getUserAvatarNickname($replyItem['uid2'], $userBindAstrInfo);
                        $nickname2 = $userAvatarNicknameData['nickname'];
                    }
                }
                $resReplyData[] = [
                    'id' => $replyItem['id'],
                    'avatar' => $replyAvatar,
                    'nickname' => $replyNickname,
                    'nickname2' => $nickname2 ?? '',
                    'create_time' => Util::timeToStr($replyItem['create_time']),
                    'content' => $replyItem['content'],
                    'good_num' => $replyItem['good_num'],
                    'is_good' => in_array($replyItem['id'], $goodCommentReplyIds, true) ? 1 : 0,
                    'is_self' => $replyItem['uid'] === $uid ? 1 : 0,
                    'owner_tag' => $replyItem['uid'] === $articleInfo['uid'] ? '本体' : '',
                ];
                $replyMinId = $replyItem['id'];
            }

            $resData[] = [
                'id' => $dataItem['id'],
                'avatar' => $avatar,
                'nickname' => $nickname,
                'create_time' => Util::timeToStr($dataItem['create_time']),
                'content' => $dataItem['content'],
                'good_num' => $dataItem['good_num'],
                'is_good' => in_array($dataItem['id'], $goodCommentIds, true) ? 1 : 0,
                'is_self' => $uid === $dataItem['uid'] ? 1 : 0,
                'astr_id' => $userBindAstrInfo[$dataItem['uid']] ?? 0,
                'owner_tag' => $ownerTag ?? '',
                'reply_num' => $replyList['total'],
                'reply_min_id' => $replyMinId,
                'reply_list' => $resReplyData,
            ];
        }

        return [
            'total' => $idDatas['total'],
            'surplus_num' => $idDatas['surplus_num'],
            'min_id' => $idDatas['min_id'],
            'data' => $resData,
        ];
    }

    public function getUserAvatarNickname(int $uid, array $uidBindAstrId = [])
    {
        $zyhsUserModel = new ZyhsUser();
        if (isset(self::$userAvatarNicknameData[$uid]))
        {
            return self::$userAvatarNicknameData[$uid];
        }
        $astrId = $uidBindAstrId[$uid] ?? 0;
        if ($astrId)
        {   // 咨询师 回复 --- 占星师 回复 消息  头像 和昵称 使用占星师 的头像和昵称
            $astrInfo = (new ZlcrAstr())->getInfoById($astrId, ['avatar', 'nickname']);
            $avatar = $astrInfo['avatar'];
            $nickname = $astrInfo['nickname'];
        } else
        {   // 普通用户回复
            $userInfo = $zyhsUserModel->getInfoById($uid, ['avatar', 'nickname']);
            $avatar = $userInfo['avatar'];
            $nickname = $userInfo['nickname'];
        }
        $avatarNicknameData = [
            'avatar' => $avatar,
            'nickname' => $nickname,
        ];
        self::$userAvatarNicknameData[$uid] = $avatarNicknameData;

        return $avatarNicknameData;
    }
}